package com.ziyear.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.ziyear.common.util.JDBCUtil;
import com.ziyear.common.util.TrainUtils;
import com.ziyear.dao.PrepDao;
import com.ziyear.dao.TrainDao;
import com.ziyear.dao.TrainSeatDao;
import com.ziyear.dao.impl.PrepDaoImpl;
import com.ziyear.dao.impl.TrainDaoImpl;
import com.ziyear.dao.impl.TrainSeatDaoImpl;
import com.ziyear.domain.Prep;
import com.ziyear.domain.Train;
import com.ziyear.domain.TrainSeat;
import com.ziyear.service.PrepService;
import org.apache.log4j.Logger;

import java.math.BigDecimal;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.List;

public class PrepServiceImpl implements PrepService {

    private PrepDao prepDao = new PrepDaoImpl();
    private TrainSeatDao trainSeatDao = new TrainSeatDaoImpl();
    private TrainDao trainDao = new TrainDaoImpl();
    private static Logger logger = Logger.getLogger(PrepServiceImpl.class);

    @Override
    public int add(Prep prep) {
        int recordNumber = 0;
        if (prep != null) {
            try {
                recordNumber = prepDao.add(prep);
            } catch (SQLException e) {
                logger.error(e.toString());
                e.printStackTrace();
            }
        } else {
            logger.debug("PrepServiceImpl.add 中 prep为null");
        }
        return recordNumber;
    }

    @Override
    public int delete(Integer prepId) {
        int recordNumber = 0;
        if (prepId != null && prepId != 0) {
            try {
                recordNumber = prepDao.delete(prepId);
            } catch (SQLException e) {
                logger.error(e.toString());
                e.printStackTrace();
            }
        } else {
            logger.debug("PrepServiceImpl.delete 中 prepId为null或0");
        }
        return recordNumber;
    }

    @Override
    public int update(Prep prep) {
        int recordNumber = 0;
        if (prep != null) {
            try {
                recordNumber = prepDao.update(prep);
            } catch (SQLException e) {
                logger.error(e.toString());
                e.printStackTrace();
            }
        } else {
            logger.debug("PrepServiceImpl.update 中 prep为null");
        }
        return recordNumber;
    }

    @Override
    public List<Prep> getAll() {
        List<Prep> list = null;
        try {
            list = prepDao.getAll();
        } catch (SQLException e) {
            logger.error(e.toString());
            e.printStackTrace();
        }
        return list;
    }

    @Override
    public List<Prep> getPrepByPmemberId(Integer pmemberId) {
        List<Prep> list = null;
        if (pmemberId != null && pmemberId != 0) {
            try {
                list = prepDao.getPrepByPmemberId(pmemberId);
            } catch (SQLException e) {
                logger.error(e.toString());
                e.printStackTrace();
            }
        } else {
            logger.debug("PrepServiceImpl.getPrepByPmemberId 中 pmemberId为null或0");
        }
        return list;
    }

    @Override
    public Prep getById(Integer prepId) {
        Prep prep = null;
        if (prepId != null && prepId != 0) {
            try {
                prep = prepDao.getById(prepId);
            } catch (SQLException e) {
                logger.error(e.toString());
                e.printStackTrace();
            }
        } else {
            logger.debug("PrepServiceImpl.getById 中 prepId为null或0");
        }
        return prep;
    }

    @Override
    public Prep queryByTrainIdAndMemberId(Integer trainId, Integer memberId) {
        try {
            return prepDao.getPrepByTrainIdAndMemberId(trainId, memberId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public boolean create(Integer memberId, Integer trainId, String seatType, Boolean waiting, String seatCode) {
        try {
            JDBCUtil.startTransaction();
            Train train = trainDao.getById(trainId);
            List<TrainSeat> trainSeats = trainSeatDao.queryUnUsedByTrainAndTypeAndCode(trainId, seatType, seatCode);
            if (CollectionUtil.isEmpty(trainSeats)) {
                trainSeats = trainSeatDao.queryUnUsedByTrainAndType(trainId, seatType);
            }
            BigDecimal price = TrainUtils.getPriceBySeatType(train, seatType);

            if (CollectionUtil.isEmpty(trainSeats)) {
                if (Boolean.TRUE.equals(waiting)) {
                    Prep prep = new Prep();
                    prep.setTrainId(trainId);
                    prep.setWaiting(true);
                    prep.setSeatType(seatType);
                    prep.setWay(false);
                    prep.setPrice(price);
                    prep.setPmemberId(memberId);
                    prep.setStartStation(train.getStartStation());
                    prep.setEndStation(train.getEndStation());
                    prep.setTrainNumber(train.getTrainNumber());
                    prep.setStartTime(train.getStartTime());
                    prep.setEndTime(train.getEndTime());
                    prep.setBooktime(new Timestamp(System.currentTimeMillis()));
                    prepDao.add(prep);
                    JDBCUtil.commit();
                    return true;
                }
                return false;
            }

            for (TrainSeat trainSeat : trainSeats) {
                int i = trainSeatDao.occupySeat(trainSeat.getSeatId());
                if (i == 0) {
                    continue;
                }
                Prep prep = new Prep();
                prep.setWaiting(false);
                prep.setSeatType(seatType);
                prep.setTrainId(trainId);
                prep.setWay(false);
                prep.setPrice(price);
                prep.setPmemberId(memberId);
                prep.setStartStation(train.getStartStation());
                prep.setEndStation(train.getEndStation());
                prep.setTrainNumber(train.getTrainNumber());
                prep.setStartTime(train.getStartTime());
                prep.setEndTime(train.getEndTime());
                prep.setTrainSeatId(trainSeat.getSeatId());
                prep.setSeatCode(trainSeat.getCarsNumber() + "号车厢 " + trainSeat.getSeatNumber());
                prep.setBooktime(new Timestamp(System.currentTimeMillis()));
                int add = prepDao.add(prep);
                if (add == 0) {
                    trainSeatDao.freed(trainSeat.getSeatId());
                    continue;
                }
                TrainUtils.reduceNumber(train, seatType);
                trainDao.update(train);
                JDBCUtil.commit();
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
            JDBCUtil.rollback();
        }
        return false;
    }

    @Override
    public boolean refund(Integer prepId) {
        try {
            JDBCUtil.startTransaction();
            Prep prep = getById(prepId);
            if (prep.isWaiting()) {
                prepDao.delete(prepId);
                return true;
            }

            TrainSeat trainSeat = trainSeatDao.queryByIdAndLock(prep.getTrainSeatId());
            if (trainSeat == null) {
                return false;
            }
            boolean alternateSeat = alternateSeat(trainSeat);
            // 没有唤醒候补需要增加座位数量
            if (!alternateSeat) {
                Train train = trainDao.getById(prep.getTrainId());
                TrainUtils.increaseNumber(train, prep.getSeatType());
                trainDao.update(train);
            }
            int delete = prepDao.delete(prepId);
            if (delete == 0) {
                throw new RuntimeException("退票失败！");
            }
            JDBCUtil.commit();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            JDBCUtil.rollback();
        }
        return false;
    }

    @Override
    public List<Prep> queryByTrainId(Integer trainId) {
        try {
            return prepDao.getPrepByTrainId(trainId);
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    private boolean alternateSeat(TrainSeat trainSeat) {
        try {
            // 释放座位失败直接返回错误
            int freed = trainSeatDao.freed(trainSeat.getSeatId());
            if (freed == 0) {
                return false;
            }
            //获取最早的候补订单，如果没有直接返回不需要占座
            Prep waitPrep = prepDao.queryEarlyWaitingPrep(trainSeat.getTrainId(), trainSeat.getSeatType());
            if (waitPrep == null) {
                return false;
            }
            // 占座 失败，目前不考虑失败  todo 添加事务
            trainSeatDao.occupySeat(trainSeat.getSeatId());

            // 更新候补订单
            waitPrep.setTrainSeatId(trainSeat.getSeatId());
            waitPrep.setSeatCode(trainSeat.getCarsNumber() + "号车厢 " + trainSeat.getSeatNumber());
            waitPrep.setWaiting(false);
            prepDao.update(waitPrep);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}
